#pragma once

#include <iostream>
#include <string>
#include <cstdio>
#include <set>

//#include "Log.hpp"

using namespace std;

class CommandExcute
{
private:
    void Load()
    {
        ifstream in(_cmd_path);
        if (!in.is_open())
        {
            Log(FATAL, "open %s error!", _cmd_path);
            return;
        }
        // 从文件中获取字典，并且存入内存中
        string line;
        while (getline(in, line))
        {
            _safe_cmd.insert(line);
        }
        Log(INFO, "Init safe cmd success!");
    }

public:
    CommandExcute(const string &com_path) : _cmd_path(com_path)
    {
        Load();
    }
    string Prefix(const string &cmd)
    {
        if(cmd.empty())
            return string();
        auto pos=cmd.find(" ");
        if(pos==string::npos)
            return cmd;
        return cmd.substr(0,pos);
    }
    bool SafeCheck(const string &cmd)
    {
        string prefixcmd=Prefix(cmd);
        auto iter = _safe_cmd.find(prefixcmd);//可以后续增加
        if (iter == _safe_cmd.end())
        {
            return false;
        }
        return true;
    }
    string Excute(const string &cmd)
    {
        string result;
        if (SafeCheck(cmd)) // 查询是否在白名单
        {
            //popen会启动一个新的进程来执行你指定的命令，并且该进程的标准输出（stdout）会被重定向到你的程序中，这样你就可以通过文件指针读取命令的输出
            FILE *fp = popen(cmd.c_str(), "r");
            if(fp==nullptr)
            {
                return "Failed";
            }
            char buffer[1024];
            while(fgets(buffer,sizeof(buffer),fp)!=NULL)
            {
                result+=buffer;
            }
            pclose(fp);
        }
        else
        {
            return "Error!\n";
        }
        return result;
    }
    ~CommandExcute()
    {
    }

private:
    string _cmd_path;
    set<string> _safe_cmd;
};
